#include "dat.h"
// #include "xjl_greedy.cpp" // 启用【单位时间最大收益——贪心】算法
// #include "time_greedy.h" // 启用【最近距离贪心】算法
// #include "simple_choose.h" // 启用【简单选择】算法
// #include "time_frac_greedy.h"
// #include "gain_greedy.h"
#include "flow.h"

char line[1024];

int getGain(int origin_gain, int time)
{
    if (time >= 9000)
        return 0.8 * origin_gain;
    double t = 1.0 - origin_gain / 9000.0;
    double r = 1.0 - sqrt(1.0 - t * t);
    r = r * 0.2 + 0.8;
    return origin_gain * r;
}

void readMapData()
{
    int robot_id = 0;
    vector<int> workbenches_in_type[10];
    for (int i = 0; i <= 100; i++)
    {
        fgets(line, sizeof line, stdin);
        if (line[0] == 'O' && line[1] == 'K')
            break;
        for (int j = 0; j < 100; j++)
        {
            if (line[j] != '.')
            {
                Location curloc = {j * 50 + 25, 4975 - i * 50};
                if (line[j] == 'A')
                {
                    robot_list[robot_id++].loc = curloc;
                }
                else
                {
                    line[j] -= '0';
                    workbench_list[workben_cnt].loc = curloc;
                    workbench_list[workben_cnt].remain_time = init_remain_time[line[j]];
                    workbenches_in_type[line[j]].push_back(workben_cnt);
                    workbench_list[workben_cnt++].type = line[j];
                }
            }
        }
    }
    for (int i = 1; i < 8; i++)
    {
        for (auto start_work_id : workbenches_in_type[i])
        {
            for (int j = 1; j <= init_action_workbench_end[i][0]; j++)
            {
                for (auto end_work_id : workbenches_in_type[init_action_workbench_end[i][j]])
                {
                    SingleAction tmp = {start_work_id, end_work_id,
                                        i,
                                        init_action_bar[i],
                                        init_action_sell[i],
                                        calculateTimeBetweenLoc(workbench_list[start_work_id].loc, workbench_list[end_work_id].loc)};
                    tmp.gain = getGain(tmp.sell - tmp.bar, tmp.time);
                    actions.push_back(tmp);
                }
            }
        }
    }
    for (auto &rob : robot_list)
    {
        rob.cur_action = actions.end();
    }
    vector<Robot *> flow_rob;
    for (int i = 0; i < 4;i++)
        flow_rob.push_back(robot_list + i);
    assainTaskForRobots(flow_rob);
}

void controlRobot(int robo_id)
{
    Robot *rob_p = robot_list + robo_id;
    if (rob_p->cur_action == actions.end())
        return;
    if (rob_p->cur_workbench_id >= 0)
    {
        Workbench &cur_workbench = workbench_list[rob_p->cur_workbench_id];
        // 机器人到达售卖点
        if (rob_p->cur_action->workbench_end == rob_p->cur_workbench_id && rob_p->load_type > 0)
        {
            printf("sell %d\n", robo_id);
            rob_p->load_type = 0;
            rob_p->cur_action = actions.end();
            return;
        }
        // 机器人到达购买点
        if (rob_p->cur_action->workbench_start == rob_p->cur_workbench_id)
        {
            if(cur_workbench.output_status == 0) {
                printf("forward %d %f\n",robo_id,0.0);
            }
            if(rob_p->load_type != 0 && rob_p->expect_loc == workbench_list[rob_p->cur_action->workbench_start].loc)
                printf("destroy %d\n", robo_id);
            printf("buy %d\n", robo_id);
            if(cur_workbench.remain_time)
                cur_workbench.output_status = 0;
            rob_p->expect_loc = workbench_list[rob_p->cur_action->workbench_end].loc;
        }
    }
    if (rob_p->expect_loc == rob_p->loc)
        return;
    double expect_angle = getAngleBetweenLoc(rob_p->loc, rob_p->expect_loc);
    double rotate_dir = expect_angle > rob_p->face_angle ? 1.0 : -1.0;
    double dangle = abs(expect_angle - rob_p->face_angle);
    if(dangle > abs(rob_p->face_angle - expect_angle))
    {
        dangle = abs(rob_p->face_angle - expect_angle);
        rotate_dir = -rotate_dir;
    }
    if(dangle > PI)
    {
        rotate_dir = -rotate_dir;
        dangle = PI2 - dangle;
    }
    if (dangle > PI_DIV_2)
        printf("forward %d %f\n", robo_id, 0.0);
    else
        printf("forward %d %f\n", robo_id, 6.0*cos(dangle));
    if (dangle > ANGLE_EPS)
        printf("rotate %d %f\n", robo_id, rotate_dir * min(PI, dangle / 0.02));
    else if (rob_p->w != 0)
        printf("rotate %d %f\n", robo_id, 0.0);
}

inline void readUntilOK()
{
    int k, ignore;
    double ignoref, x, y;
    scanf("%d%d", &money, &k);
    for (int i = 0; i < k; i++)
    {
        Workbench &cur_work = workbench_list[i];
        scanf("%d%lf%lf%d%d%d", &ignore, &ignoref, &ignoref,
              &cur_work.remain_time,
              &cur_work.raw_material_status,
              &cur_work.output_status);
    }
    for (int i = 0; i < 4; i++)
    {
        Robot &cur_rob = robot_list[i];
        scanf("%d%d%lf%lf%lf%lf%lf%lf%lf%lf",
              &cur_rob.cur_workbench_id,
              &cur_rob.load_type,
              &ignoref,
              &ignoref,
              &cur_rob.w,
              &ignoref, &ignoref,
              &cur_rob.face_angle,
              &x, &y);
        cur_rob.loc.x = round(x * 100);
        cur_rob.loc.y = round(y * 100);
    }
    scanf("%s", line);
}

int main()
{
    readMapData();
    puts("OK");
    fflush(stdout);
    int frameID;
    vector<Robot *> free_rob;
    while (scanf("%d", &frameID) != EOF)
    {
        printf("%d\n", frameID);
        readUntilOK();
        free_rob.clear();
        for(int i = 0;i < 4;i++)
        {
           if(robot_list[i].cur_action == actions.end())
                free_rob.push_back(robot_list + i);
        }
        if(!free_rob.empty())
           assainTaskForRobots(free_rob);
        for (int i = 0; i < 4; i++)
        {
            controlRobot(i);
        }
        puts("OK");
        fflush(stdout);
    }
    return 0;
}
